﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using XMLGener.GUI;
using XMLGener.Utils;
using XMLGener.Data;

namespace XMLGener
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// File dialog for opening X-temlates
        /// </summary>
        OpenFileDialog openXMLFileDialog = null;
        
        /// <summary>
        /// File dialog for saving X-templates
        /// </summary>        
        SaveFileDialog saveXMLFileDialog = null;

            
        /// <summary>
        /// Main form consturctor extended 
        /// by custom components initialization
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            cutomComponentInitialization();
        }

        /// <summary>
        /// Create and set custom components
        /// </summary>
        private void cutomComponentInitialization()
        {
            // init open dialog
            openXMLFileDialog = new OpenFileDialog();
            openXMLFileDialog.Filter = "XTemplate (*.xtl)|*.xtl";
            openXMLFileDialog.InitialDirectory = "templates";

            //init save dialog
            saveXMLFileDialog = new SaveFileDialog();
            saveXMLFileDialog.Filter = "XTemplate (*.xtl)|*.xtl";
            saveXMLFileDialog.InitialDirectory = "templates";

        }


        private void btRun_Click(object sender, EventArgs e)
        {
            if (this.selectedPanel == null)
                return;
            if (this.selectedPanel.doc.isNew)
            {
                if (!saveWithDialog())
                    return;
            }
            else 
            { 
                saveFile(); 
            }
            

            ProcessForm pf = new ProcessForm(this.selectedPanel.doc.sourceFile);
            pf.Show();
        }

        private void miExit_Click(object sender, EventArgs e)
        {
            this.Close();
        }   

        private void MainForm_Load(object sender, EventArgs e)
        {
            XLogger.instance.errorEvent+=this.errorLogHandler ;
            initializeSettings();
        }

        private void initializeSettings()
        {
            XModuleManager.loadModules();
            XSettings.loadSettings();
        }

        delegate void errorLogHandlerCallBack(XLogMessage message);

        private void errorLogHandler(XLogMessage message)
        {

            if (this.InvokeRequired)
            {
                errorLogHandlerCallBack d = new errorLogHandlerCallBack(errorLogHandler);
                this.Invoke(d, new object[] { message });
            }
            else
            {
                if (lf == null)
                {
                    lf = new LogForm();
                    //lf.Show();
                }
                lf.showThisForm();
                lf.addMessage(message);
            }
        }
        
       

       

        private LogForm lf = null;
        
        private void miShowLog_Click(object sender, EventArgs e)
        {
            if (lf==null)
                lf = new LogForm();
            lf.Show();
        }

        
        private void miSave_Click(object sender, EventArgs e)
        {
            saveFile();   
        }

        private void btSaveFile_MouseUp(object sender, MouseEventArgs e)
        {
            saveFile();
        }
        /// <summary>
        ///  Open file and show it in new tab.
        /// </summary>
        private void miOpen_Click(object sender, EventArgs e)
        {
            openFile();
        }


        private void miNew_Click(object sender, EventArgs e)
        {
            // if file name is null, it means to create new document
            openDocument(null);
        }


        /// <summary>
        /// Open XTemplate
        /// </summary>
        private void openFile()
        {
            if (openXMLFileDialog.ShowDialog() == DialogResult.OK)
            {
                openDocument(openXMLFileDialog.FileName);
            }
        }

        /// <summary>
        /// Save document.
        /// </summary>
        private bool saveFile()
        {
            // if document is new, select file name to be saved into it
            if (!this.selectedPanel.doc.isNew)
            {
                this.selectedPanel.saveDocument();
                return true;
            }
            return saveWithDialog();
        }

        /// <summary>
        /// Save document
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void miSaveAs_Click(object sender, EventArgs e)
        {
            saveWithDialog();
        }
    
        private bool saveWithDialog()
        {
            if (saveXMLFileDialog.ShowDialog() == DialogResult.OK)
            {
                this.selectedPanel.saveAsDocument(saveXMLFileDialog.FileName);
                if (this.openedDocuments.ContainsKey(saveXMLFileDialog.FileName))
                {
                    XTemplatePanel oldPanel = this.openedDocuments[saveXMLFileDialog.FileName];
                    this.tabNavigtor.TabPages.Remove(oldPanel.parentTab);
                    this.openedDocuments.Remove(saveXMLFileDialog.FileName);
                }
                return true;
            }
            return false;
        }

        private Dictionary<string, XTemplatePanel> openedDocuments = new Dictionary<string, XTemplatePanel>();


        /// <summary>
        /// Load document by creating XTemplatePanel which constructor
        /// argument is file name.
        /// </summary>
        /// <param name="filename">Source file of XTemplate</param>
        private void openDocument(String filename)
        {
            if (filename!=null && openedDocuments.ContainsKey(filename))
            {
                XTemplatePanel panel = openedDocuments[filename];
                this.tabNavigtor.SelectedIndex = (this.tabNavigtor.Controls.IndexOf(panel.parentTab));
                return;
            }
            TabPage newTab = new TabPage();
            XTemplatePanel newPanel = new XTemplatePanel(filename, newTab);
            newPanel.Name = "xpanel";
            newPanel.onTreeNodeSelect += this.onTreeNodeSelect;
            newPanel.openDocumentEvent += this.onOpenDocument;
            newPanel.Dock = DockStyle.Fill;
            newTab.Controls.Add(newPanel);
            if (filename != null)
                openedDocuments.Add(filename, newPanel);
            this.tabNavigtor.Controls.Add(newTab);
            this.tabNavigtor.SelectedIndex = (this.tabNavigtor.Controls.IndexOf(newTab));
           
            onTreeNodeSelect(newPanel, newPanel.getSelectedTreeNode);
        
        }

        /// <summary>
        /// Close document.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void miClose_Click(object sender, EventArgs e)
        {
            if (this.tabNavigtor.SelectedTab == null)
                return;
            TabPage currentTab = this.tabNavigtor.SelectedTab;
            int index = currentTab.Controls.IndexOfKey("xpanel");
            selectedPanel = (XTemplatePanel)this.tabNavigtor.SelectedTab.Controls[index];
            if (selectedPanel.doc!=null && selectedPanel.doc.sourceFile!=null)
                this.openedDocuments.Remove(selectedPanel.doc.sourceFile);
            this.tabNavigtor.TabPages.Remove(currentTab);
            tabNavigtor_SelectedIndexChanged(null,null);   
        }

        private void tabNavigtor_SelectedIndexChanged(object sender, EventArgs e)
        {
            TabPage currentTab = this.tabNavigtor.SelectedTab;
            if (currentTab == null)
            {
                onTreeNodeSelect(null, null);
                return;
            }
            int index = currentTab.Controls.IndexOfKey("xpanel");
            selectedPanel = (XTemplatePanel)this.tabNavigtor.SelectedTab.Controls[index];
            selectedNode = selectedPanel.getSelectedTreeNode;
            onTreeNodeSelect(selectedPanel,selectedNode);
            selectedPanel.refreshTreeView();
        }


        /// <summary>
        /// Active (visible) panel
        /// </summary>
        private XTemplatePanel selectedPanel;
        
        /// <summary>
        /// Selected node in tree view
        /// </summary>
        private XTreeNode selectedNode;

        /// <summary>
        /// This method is event handler on action, when
        /// user selects node in treeview (or if it is selected programmaticaly)
        /// Method set selected node from active tab panel ( = seleted panel)
        /// and it changes buttons for editing.
        /// </summary>
        /// <param name="sender">XTemplate panel</param>
        /// <param name="node">Selected node</param>
        private void onTreeNodeSelect(XTemplatePanel sender,XTreeNode node)
        {
            // if selected panel differs from last
            if (this.selectedPanel != sender)
                this.selectedPanel = sender;
            this.selectedNode = node;

            // set default ability
            bool disableAll = (selectedPanel == null);
            bool enableNewElement = true;
            bool enableNewElements = true;
            bool enableNewAttribute = true;
            bool enableNetTextNode = true;
            bool enableDeleteNode = true;
            bool enableMoveButtons = true;
            bool enableNewDataType = true;
            bool isTextNode = false;
            bool editingNodeEnabled = true;
            bool isInherited = false;


            // set ability according to selected node type
            if (this.selectedNode != null && this.selectedNode.xnode != null)
            {

                if (this.selectedNode.xnode.isCopy)
                    editingNodeEnabled = false;

                XMLGenerElement xelem = this.selectedNode.xnode as XMLGenerElement;
                
                if (xelem != null && xelem.contentType != XMLGenerElement.TYPE_ONLY_ELEMENTS)
                    isTextNode = true;
                if (xelem != null && xelem.baseType!=null)
                    isInherited = true;
               

                switch (this.selectedNode.xnode.xtype)
                {
                    case XMLGenerNode.XNodeType.ELEMENT:
                        if (isTextNode)
                        {
                            enableNewElement = false;
                            enableNewElements = false;
                            enableNewAttribute = false;
                            enableNetTextNode = false;
                        }
                        enableNewDataType = false;
                        break;
                    case XMLGenerNode.XNodeType.ATTRIBUTE:
                    case XMLGenerNode.XNodeType.TEXTNODE:
                        enableNewElement = false;
                        enableNewElements = false;
                        enableNewAttribute = false;
                        enableNetTextNode = false;
                        enableNewDataType = false;
                        break;
                    case XMLGenerNode.XNodeType.DATATYPES:
                        enableMoveButtons = false;
                        enableDeleteNode = false;
                        enableNewElement = false;
                        enableNewElements = false;
                        enableNewAttribute = false;
                        enableNetTextNode = false;
                        break;
                    case XMLGenerNode.XNodeType.DATATYPE:
                        enableNewElement = false;
                        enableNewElements = false;
                        enableNewAttribute = false;
                        enableNetTextNode = false;
                        break;
                    case XMLGenerNode.XNodeType.ELEMENTS:
                        enableNewAttribute = false;
                        enableNewDataType = false;
                        break;
                    case XMLGenerNode.XNodeType.ELEMENTTYPES:
                        enableNewElements = false;
                        enableNewAttribute = false;
                        enableNetTextNode = false;
                        enableNewDataType = false;
                        enableMoveButtons = false;
                        enableDeleteNode = false;
                        break;
                    default:
                        disableAll = true;
                        break;
                }

                if (this.selectedNode.xnode is XMLGenerMainElement)
                {
                    enableDeleteNode = false;
                    enableMoveButtons = false;
                }
                if (isInherited)
                    editingNodeEnabled = false;
            }
            else
            {
                disableAll = true;
            }

            btRun.Enabled = !disableAll;
            btCalculate.Enabled = !disableAll;
            btDefinition.Enabled = !disableAll;
            btMoveDown.Enabled = !disableAll && enableMoveButtons && editingNodeEnabled;
            btMoveUp.Enabled = !disableAll && enableMoveButtons && editingNodeEnabled;
            btRemoveNode.Enabled = !disableAll && enableDeleteNode && editingNodeEnabled;
            toolBtAddAttribute.Enabled = !disableAll && enableNewAttribute && editingNodeEnabled;
            toolBtAddElement.Enabled = !disableAll && enableNewElement && editingNodeEnabled;
            toolBtAddElements.Enabled = !disableAll && enableNewElements && editingNodeEnabled;
            toolBtAddTexContent.Enabled = !disableAll && enableNetTextNode && editingNodeEnabled;
            toolBtAddDataType.Enabled = !disableAll && enableNewDataType && editingNodeEnabled;
            btSaveFile.Enabled = !disableAll;
            btCloseDocument.Enabled = !disableAll;
            miSave.Enabled = !disableAll;
            miSaveAs.Enabled = !disableAll;
            miClose.Enabled = !disableAll;

        }

        private void onOpenDocument(XTemplatePanel sender, string filename)
        {

            this.openDocument(filename);
        }



        /// <summary>
        /// Add new element under selected node.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolBtAddElement_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.addNewElement();
        }

        /// <summary>
        /// Add elements under selected node.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolBtAddElements_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.addNewElements();
        }

        /// <summary>
        /// Add attribute under selected node.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolBtAddAttribute_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.addNewAttribute();
        }


        private void btAddTexContent_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.addNewTextNode();
        }

        private void btRemoveNode_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.removeNode();

        }

        private void btMoveDown_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.moveNodeDown();

        }

        private void btMoveUp_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.moveNodeUp();

        }

        //this.tabPage1.Enter += new System.tabPage_Changed(this.tabPage1_Enter);

        private void tabPage_Changed(object sender, EventArgs e)
        {
            if (! (sender is XTemplatePanel))
                return;
            XTemplatePanel panel = (XTemplatePanel)sender;
            onTreeNodeSelect(panel, panel.getSelectedTreeNode);
            
        }

        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            this.selectedPanel.doc.preCalculate();
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            this.selectedPanel.doc.generateDefinitionDocument();
        }

        private void toolBtAddDataType_Click(object sender, EventArgs e)
        {
            if (selectedPanel == null)
                return;
            selectedPanel.addNewDataTypeNode();
        }

       

        

        

        



    }
}
